#include <workerManager.hpp>

const char* FILENAME = "empFile.txt";



System::WorkerManager::WorkerManager()
{
    /* 三种打开方式 */
    // 1.文件不存在
    std::ifstream ifs;
    ifs.open(FILENAME, std::ios::in);  // 读文件
    if (!ifs.is_open()) {
        std::cout << "文件不存在" << std::endl;
        // 初始化属性
        this->m_EmpNum = 0;
        // 初始化数组指针
        this->m_EmpArray = nullptr;
        // 初始化文件是否为空
        this->m_FileIsEmpty = true;
        ifs.close();
        return;
    }
    
    // 2.文件存在，但为空
    char ch;        // 创建一个字符
    ifs >> ch;      // 尝试将文件内的一个字符读入至 ch 若是无字符可以读入,那么 ifs 将进入 eof 此时 if.eof() == true; 
    if (ifs.eof()) {
        std::cout << "文件为空" << std::endl;
        // 初始化属性
        this->m_EmpNum = 0;
        // 初始化数组指针
        this->m_EmpArray = nullptr;
        // 初始化文件是否为空
        this->m_FileIsEmpty = true;
        ifs.close();
        return;
    }

    // 3.文件存在,并且记录数据
    this->m_FileIsEmpty = false;
    int num = this->get_EmpNum();
    std::cout << "职工的人数为:" << num << std::endl;
    this->m_EmpNum = num;

    // 开辟空间
    this->m_EmpArray = new name_Worker::Worker*[this->m_EmpNum];

    // 将文件中的数据存到数组中
    this->init_Emp();

    // 测试代码
    // for (int i = 0; i < this->m_EmpNum; i++)
    // {
    //     std::cout << "职工编号为：" << this->m_EmpArray[i]->m_Id 
    //               << " 部门编号为：" << this->m_EmpArray[i]->m_DeptId 
    //               << " 职工姓名为：" << this->m_EmpArray[i]->m_Name << std::endl;
    // }
}


System::WorkerManager::~WorkerManager()
{
    if (this->m_EmpArray != nullptr) {
        delete[] this->m_EmpArray;
        this->m_EmpArray = nullptr;
    }
}

int workerIndex = 0;
/* 如果职工信息文件存在且有信息，就初始化职工信息 */
void System::WorkerManager::init_Emp()
{
    std::ifstream ifs;
    ifs.open(FILENAME, std::ios::in);

    int id;
    int dId;
    std::string name;
    while (ifs >> id >> dId >> name)
    {
        name_Worker::Worker * worker = nullptr;
        if (dId == 1) {             // 普通职工
            worker = new name_Worker::Employee(id, dId, name);
        } else if (dId == 2) {      // 经理
            worker = new name_Worker::Manager(id, dId, name);
        } else if (dId == 3) {      // 老板
            worker = new name_Worker::Boss(id, dId, name);
        }
        this->m_EmpArray[workerIndex] = worker;
        workerIndex ++;
    }
    ifs.close();
}


/*展示菜单*/
void System::WorkerManager::Show_Menu()
{
    std::cout << "====================================================" << std::endl;
    std::cout << "=============== 欢迎使用职工管理系统! ==============" << std::endl;
    std::cout << "================== 0.退出管理程序 ==================" << std::endl;
    std::cout << "================== 1.显示职工信息 ==================" << std::endl;
    std::cout << "================== 2.增加职工信息 ==================" << std::endl;
    std::cout << "================== 3.删除离职职工 ==================" << std::endl;
    std::cout << "================== 4.修改职工信息 ==================" << std::endl;
    std::cout << "================== 5.查找职工信息 ==================" << std::endl;
    std::cout << "================== 6.按照编号排序 ==================" << std::endl;
    std::cout << "================== 7.清空所有文档 ==================" << std::endl;
    std::cout << "====================================================" << std::endl;
    std::cout << std::endl;
}

/*退出系统*/
void System::WorkerManager::ExitSystem()
{
    std::cout << "欢迎下次使用" << std::endl;
    exit(0);
}

/*添加职工*/
void System::WorkerManager::Add_Emp()
{
    std::cout << "请输入添加职工数量：" << std::endl;
    int addNum = 0;     // 保存用户的输入
    std::cin >> addNum;
    if (addNum > 0) {
        // 添加
        // 计算添加新空间大小
        const int newSize = this->m_EmpNum + addNum;  // 新空间大小 = 原来记录的人数 + 新增人数

        // 开辟新空间
        auto ** newSpace = new name_Worker::Worker *[newSize];

        // 将原来空间下的数据，拷贝到新空间下
        if (this->m_EmpArray != nullptr) {
            for (int i = 0; i < this->m_EmpNum; i++) {
                newSpace[i] = this->m_EmpArray[i];
            }
        }
        // 批量添加新数据
        std::string name;// 职工姓名
        int id;     // 职工编号
        int dSelect;// 部门
        for (int i = 0; i < addNum; i++) {
            std::cout << "请输入第" << (i+1) << "个新职工的姓名：" << std::endl;
            std::cin >> name;
            std::cout << "请输入第" << (i+1) << "个新职工的编号：" << std::endl;
            std::cin >> id;
            std::cout << "请选择该职工的岗位： " << std::endl;
            std::cout << "1.普通职工" << std::endl << "2.经理" << std::endl << "3.老板" << std::endl;
            std::cin >> dSelect;

            name_Worker::Worker * worker = nullptr;
            switch (dSelect) {
                case 1:
                    worker = new name_Worker::Employee(id, 1, name);
                    break;
                case 2:
                    worker = new name_Worker::Manager(id, 2, name);
                    break;
                case 3:
                    worker = new name_Worker::Boss(id, 3, name);
                    break;
                default:
                    std::cout << "输入岗位编号有误，无法创建职工。" << std::endl;
                    continue;
            }
            // 将创建的职工职责，保存到数组中
            newSpace[this->m_EmpNum + i] = worker;
        }

        // 释放原有空间
        delete [] this->m_EmpArray;
        // 更新空间的指向
        this->m_EmpArray = newSpace;
        // 更新新的职工人数
        this->m_EmpNum = newSize;
        // 更新职工不为空的标志
        this->m_FileIsEmpty = false;

        this->save_File();  // 保存文件
        // 提示添加成功
        std::cout << "成功添加" << addNum << "名新职工！" << std::endl;

    } else {
        // 不添加
        std::cout << "输入数据有误!" << std::endl;
    }

    // 按任意键清屏返回上级目录……
    this->clear();

}

/* 保存文件 */
void System::WorkerManager::save_File()
{
    std::ofstream ofs;
    ofs.open(FILENAME, std::ios::out);         // 用输出的方式打开文件 -- 写文件

    // 将每个人数据写入到文件中
    for (int i = 0; i < this->m_EmpNum; i++) {
        ofs << this->m_EmpArray[i]->m_Id << " "
            << this->m_EmpArray[i]->m_DeptId << " "
            << this->m_EmpArray[i]->m_Name << std::endl;
    }

    // 关闭文件
    ofs.close();
}

/* 统计文件中人数 */
int System::WorkerManager::get_EmpNum()
{
    std::ifstream ifs;
    ifs.open(FILENAME, std::ios::in);   // 打开文件 读
    int id;
    int dId;
    std::string name;

    int num = 0;
    while (ifs >> id >> dId >> name) {
        num++;
    }
    ifs.close();
    return num;
}


// 显示职工信息
void System::WorkerManager::Show_Emp()
{
    // 判断文件是否为空
    if (this->m_FileIsEmpty) {
        std::cout << "文件为空" << std::endl;
    } else {
        // 显示职工信息
        for (int i = 0; i < this->m_EmpNum; i++) {
            // 利用多态调用程序接口
            this->m_EmpArray[i]->showInfo();
        }
    }

    // 按任意键清屏返回上级目录……
    this->clear();
}


/* 按照职工编号判断职工是否存在，若存在返回会职工在数组中的位置，不存在返回 -1 */
int System::WorkerManager::IsExist(int id)
{
    int index = -1;
    for(int i = 0; i < this->m_EmpNum; i++)
    {
        if (this->m_EmpArray[i]->m_Id == id)
        {
            index = i;
            break;
        }
    }
    return index;
}

/* 删除职工 */
void System::WorkerManager::Del_Emp()
{
    if (this->m_FileIsEmpty) {
        std::cout << "文件不存在或记录为空！" << std::endl;
    } else {
        // 按照职工编号删除
        std::cout << "请输入想要删除的职工编号：" << std::endl;
        int id = 0;
        std::cin >> id;

        int index = 0;
        index = this->IsExist(id);
        if (index != -1) {      // 说明职工存在，并且要删除掉 index 位置上的职工
            // 数据前移
            for (int i = index;i < this->m_EmpNum - 1; i++) {
                this->m_EmpArray[i] = this->m_EmpArray[i + 1];
            }
            this->m_EmpArray[m_EmpNum - 1] = nullptr;    // 最后一个职工置空

            this->m_EmpNum --;// 更新数组中记录的人员个数
            if (this->m_EmpNum == 0)
                this->m_FileIsEmpty = true;
            this->save_File();
            // 按任意键清屏返回上级目录……
            std::cout << "删除成功" << std::endl << "按回车键返回上级目录..." << std::endl;
            this->clear();
        } else {
            std::cout << "删除失败，未找到该职工！" << std::endl;
            // 按任意键清屏返回上级目录……
            this->clear();
        }
    }
}

/* 修改职工 */
void System::WorkerManager::Mod_Emp()
{
    if (this->m_FileIsEmpty) {
        std::cout << "文件不存在或记录为空！" << std::endl;
    } else {
        std::cout << "请输入要修改的职工编号：" << std::endl;
        int id = 0;
        std::cin >> id;

        int ret = this->IsExist(id);
        if (ret != -1) {
            // 查找找到编号的职工
            delete this->m_EmpArray[ret];
            int newId = 0;
            int dSelect = 0;
            std::string newName = "";

            std::cout << "查到：" << id << " 号职工，请输入新职工号" << std::endl;
            std::cin >> newId;

            std::cout << "请输入新职工部门编号：" << std::endl;
            std::cout << "1.普通职工" << std::endl << "2.经理" << std::endl << "3.老板" << std::endl;
            std::cin >> dSelect;

            std::cout << "请输入新职工姓名：" << std::endl;
            std::cin >> newName;
            name_Worker::Worker * worker = nullptr;
            switch (dSelect) 
            {
            case 1:
                worker = new name_Worker::Employee(newId, dSelect, newName);
                break;
            case 2:
                worker = new name_Worker::Manager(newId, dSelect, newName);
                break;
            case 3:
                worker = new name_Worker::Boss(newId, dSelect, newName);
                break;
            default:
                break;
            }

            // 更新数据 到数组
            this->m_EmpArray[ret] = worker;

            std::cout << "修改成功" << std::endl;
            this->save_File();
        } else {
            std::cout << "修改失败，未找到该职工！" << std::endl;
        }
        // 按任意键清屏返回上级目录……
        this->clear();
    }
}


/* 查找职工 */
void System::WorkerManager::Find_Emp()
{
    if (this->m_FileIsEmpty) {
        std::cout << "文件不存在或记录为空！" << std::endl;
    } else {
        std::cout << "请输入查找的方式：" << std::endl;
        std::cout << "1.按职工编号查找" << std::endl;
        std::cout << "2.按职工姓名查找" << std::endl;
        int id = 0;
        std::string name = "";
        int select = 0;
        std::cin >> select;
        if (select == 1) {
            // 按照职工编号查找
            std::cout << "请输入职工编号" << std::endl;
            std::cin >> id;
            int ret = this->IsExist(id);
            if (ret != -1) {
                this->m_EmpArray[ret]->showInfo();
                // 按任意键清屏返回上级目录……
                this->clear();
            } else {
                std::cout << "查找的职工不存在！" << std::endl;
                // 按任意键清屏返回上级目录……
                this->clear();
            }
        } else if (select == 2) {
            // 按职工姓名查找
            std::cout << "请输入要查找职工的姓名：" << std::endl;
            std::cin >> name;
            int i;
            for (i = 0; i < this->m_EmpNum; i++) {
                if(this->m_EmpArray[i]->m_Name == name) {
                    this->m_EmpArray[i]->showInfo();
                    // break;
                } else if ((this->m_EmpArray[m_EmpNum - 1]->m_Name) != name) {
                    std::cout << "查无此人！" << std::endl;
                    // 按任意键清屏返回上级目录……
                    this->clear();
                    return;
                }
            }
            // 按任意键清屏返回上级目录……
            this->clear();
                
        } else {
            std::cout << "输入的选项有误！" << std::endl;
            // 按任意键清屏返回上级目录……
            this->clear();
        }
    }
}

/* 清屏 */
void System::WorkerManager::clear()
{
    // 按任意键清屏返回上级目录……
    std::cout << "按回车键返回上级目录..." << std::endl;
    // std::cin.ignore()函数可以接受两个参数：要忽略的字符数和一个分界字符。当它被调用时，会从输入流中读取并忽略指定数量的字符，或者直到遇到了第二个参数指定的分界字符
    // 第一个参数指定了ignore函数需要忽略的最大字符数。在这种情况下，它基本上告诉ignore函数忽略直到下一个换行符\n之前的所有字符。
    // 第二个参数'\n'是分界字符，告诉ignore函数在读取到换行符时停止忽略。 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    std::cin.get(); // 等待用户按下任意键

    std::cout << "\033[2J\033[H";
}


/* 按照职工编号排序 */
void System::WorkerManager::Sort_Emp()
{
    if (this->m_FileIsEmpty) {
        std::cout << "文件不存在或记录为空！" << std::endl;
    } else {
        std::cout << "请选择排序方式：" << std::endl;
        std::cout << "1.按职工号进行升序排列" << std::endl;
        std::cout << "2.按职工号进行降序排列" << std::endl;
        int select = 0;
        std::cin >> select;

        // 交换排序
        for (int i = 0; i < m_EmpNum; i++) {
            int MinOrMax = i;   // 声明最小值或者最大值的下标
            for (int j = i + 1; j < m_EmpNum; j++) {
                if (select == 1) {  // 升序
                    if (this->m_EmpArray[MinOrMax]->m_Id > this->m_EmpArray[j]->m_Id) {
                        MinOrMax = j;
                    }
                } else {            // 降序
                    if (this->m_EmpArray[MinOrMax]->m_Id < this->m_EmpArray[j]->m_Id) {
                        MinOrMax = j;
                    }
                } 

            }
            // 判断一开始认定的最大值或最小值 是不是 计算的最小值或最大值 ，如果不是 交换数据
            if (MinOrMax != i) {
                name_Worker::Worker * temp = this->m_EmpArray[i];
                this->m_EmpArray[i] = this->m_EmpArray[MinOrMax];
                this->m_EmpArray[MinOrMax] = temp;
            }    
        }
    }
    std::cout << "排序成功！排序后的结果为: " << std::endl;
    this->save_File();      // 排序后的结果保存到文件中
    this->Show_Emp();       // 显示排序后的结果
}


void System::WorkerManager::Clean_File()
{
    std::cout << "请确认是否清空文件！" << std::endl;
    std::cout << "1.确认" << std::endl;
    std::cout << "2.返回" << std::endl;

    int select = 0;
    std::cin >> select;
    if (select == 1) {
        // 打开模式 ios::trunc 如果存在删除文件并重新创建
        std::ofstream ofs(FILENAME, std::ios::trunc);
        ofs.close();

        if (this->m_EmpArray != nullptr) {
            for (int i = 0; i < this->m_EmpNum; i++) {
                if (this->m_EmpArray[i] != nullptr) {
                    delete this->m_EmpArray[i];
                }
            }
            delete [] this->m_EmpArray;
            this->m_EmpArray = nullptr;
            this->m_EmpNum = 0;
            this->m_FileIsEmpty = true;
        }
        std::cout << "清空文件成功！" << std::endl;
        // 按任意键清屏返回上级目录……
        this->clear();
    } else {
        // 按任意键清屏返回上级目录……
        std::cout << "\033[2J\033[H";
        return;
    }
}
